﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceProcess;
using System.Diagnostics;
using System.IO;
using System.Threading;
using Cherry.Agile.ServiceModel.Runtime;
using Cherry.Agile.Logging;

namespace Cherry.Agile.ServiceModel.Services {

    public class EnterpriseService : ServiceBase {
        static string _appName;

        static string AppName {
            get {
                if (_appName == null) {
                    var file = System.Reflection.Assembly.GetEntryAssembly().Location;

                    if (File.Exists(file)) {
                        var cfg = System.Configuration.ConfigurationManager.OpenExeConfiguration(file);
                        _appName = cfg.AppSettings.Settings["service.name"].Value;
                    } else
                        _appName = System.Configuration.ConfigurationManager.AppSettings.Get("service.name");
                    if (string.IsNullOrEmpty(_appName))
                        throw new ArgumentNullException("invalid config setting ,could not found service.name setting in the config file.");
                }
                return _appName;
            }
        }

        public EnterpriseService() {
            InitializeComponent();
        }

        protected virtual IServiceFilter Filter {
            get {
                return ServiceFilter.Empty;
            }
        }
        
        protected virtual IEventListener Listener {
            get {
                return null;
            }
        }
        //EventLog _log = new EventLog("Application");
        //public override EventLog EventLog {
        //    get {
        //        return _log;
        //    }
       // }

        private void DoStart(string[] args) {
            if (Environment.UserInteractive) {
                Console.ForegroundColor = ConsoleColor.Green;
                var ls = new ConsoleTraceListener();
                if (args.Any(c => c == "-l"))
                    System.Diagnostics.Trace.Listeners.Add(ls);

                OnStart(args);

                Console.ForegroundColor = ConsoleColor.Green;
                Console.WriteLine("all services are ready...");
                Console.ForegroundColor = ConsoleColor.White;
                Console.WriteLine("press X to exit,L open or close log");
                Console.ForegroundColor = ConsoleColor.Green;
                var key = Console.ReadKey();

                while (true) {
                    Console.ForegroundColor = ConsoleColor.White;
                    Console.WriteLine();
                    if (key.Key == ConsoleKey.X)
                        break;
                    else if (key.Key == ConsoleKey.L) {
                        if (!System.Diagnostics.Trace.Listeners.Contains(ls)) {
                            Console.WriteLine("log is opend.");
                            System.Diagnostics.Trace.Listeners.Add(ls);
                        } else {
                            Console.WriteLine("log is closed.");
                            System.Diagnostics.Trace.Listeners.Remove(ls);
                            Console.Clear();
                        }
                    } else if (key.Key == ConsoleKey.C)
                        Console.Clear();
                    Console.WriteLine("press X to exit,L open or close log");
                    Console.ForegroundColor = ConsoleColor.Green;
                    key = Console.ReadKey();
                }

                Stop();
            } else {
                System.ServiceProcess.ServiceBase[] ServicesToRun;
                ServicesToRun = new System.ServiceProcess.ServiceBase[] { this };
                System.ServiceProcess.ServiceBase.Run(ServicesToRun);
            }
        }

        public void Start(string[] args) {
            try {
                DoStart(args);
            } catch (Exception ex) {
                if (Environment.UserInteractive) {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine("Error:\r\n=====================================");
                    Console.WriteLine(ex.Message);

                    if (ex.InnerException != null) {
                        Console.WriteLine(ex.InnerException.Message);
                    }

                    Console.WriteLine(ex.StackTrace);
                    Console.WriteLine("press any key to exit.");
                    
                } else
                    throw;
            }
        }

        ILogger log = Cherry.Agile.Logging.LoggingManager.GetLogger();
        protected virtual void InitializeComponent() {
            this.EventLog.Source = AppName;
            this.AutoLog = true;
            this.ServiceName = AppName;
            Cherry.Agile.Globalization.MultilingualManager.SwichCulture(string.Empty);
            //if (!System.Diagnostics.EventLog.SourceExists(AppName)) {
            //    System.Diagnostics.EventLog.CreateEventSource(AppName,"Application");
            //}
            //_log.Source = AppName;// "System";
            //_log.Log = "Application";
        }

        protected override void OnStart(string[] args) {
            //this.EventLog.WriteEntry("service starting", EventLogEntryType.Information);
            log.Info("service starting");
            string basicAddress = System.Configuration.ConfigurationManager.AppSettings["service.address"];
            ServiceFactory.StartService(basicAddress,Filter,Listener,(c) => {},
                (ex) => {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine("start error:" + ex.Message);
                    log.Error("service started has error:" + ex.Message, ex);
                    //EventLog.WriteEntry("service started has error:" + ex.Message, EventLogEntryType.Warning);
                    Console.ForegroundColor = ConsoleColor.Green;
                });
            log.Info("service started");
            //this.EventLog.WriteEntry("service started", EventLogEntryType.Information);
        }
        
        protected override void OnStop() {
            base.OnStop();
            //this.EventLog.WriteEntry("service stoped", EventLogEntryType.Information);
            log.Info("service stoped");
        }

        protected override void OnPause() {
            base.OnPause();
            log.Info("service paused");
            //this.EventLog.WriteEntry("service paused", EventLogEntryType.Information);
        }

        
    }
}
